/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.rational.sheet.table.adapter;

/**
 *
 * @author Overmind
 */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.datatransfer.*;
import java.io.IOException;
import java.util.*;
/**
 * ExcelAdapter enables Copy-Paste Clipboard functionality on JTables.
 * The clipboard data format used by the adapter is compatible with
 * the clipboard format used by Excel. This provides for clipboard
 * interoperability between enabled JTables and Excel.
 */
public class ClipborardTableAdapter
    implements ActionListener
{
    private static final KeyStroke copy;
    private static final KeyStroke paste;
    private static final String rowDelim = "\n";
    private static final String columnDelim = "\t";
    
    private Clipboard system;
    private JTable table;

    static
    {
        copy = KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK, false);
        paste = KeyStroke.getKeyStroke(KeyEvent.VK_V, ActionEvent.CTRL_MASK, false);
    }
    
    {
        
        system = Toolkit.getDefaultToolkit().getSystemClipboard();
    }
    
    public ClipborardTableAdapter()
    {
        this(null);
    }
    
    public ClipborardTableAdapter(JTable table)
    {
        setTable(table);
    }
    
    public JTable getTable()
    {
        return table;
    }
    
    public final void setTable(JTable newTable)
    {
        if(table != null)
        {
            table.unregisterKeyboardAction(copy);
            table.unregisterKeyboardAction(paste);
        }
        
        table = newTable;
        
	if(table != null)
        {
            table.registerKeyboardAction(this, "Copy", copy, JComponent.WHEN_FOCUSED);
	    table.registerKeyboardAction(this, "Paste", paste, JComponent.WHEN_FOCUSED);
        }
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        if (e.getActionCommand().compareTo("Copy") == 0)
        {
            StringBuilder builder = new StringBuilder();

            int numcols = table.getSelectedColumnCount();
            int numrows = table.getSelectedRowCount();
            int[] rowsselected = table.getSelectedRows();
            int[] colsselected = table.getSelectedColumns();
            
            for (int i = 0; i < numrows; i++)
            {
                for (int j = 0; j < numcols; j++)
                {
                    builder.append(table.getValueAt(rowsselected[i], colsselected[j]));
                    
                    for(int k = colsselected[j]; j+1 != numcols && k < colsselected[j+1];++k)
                    {
                        builder.append(columnDelim);
                    }
                }
                
                for(int j = rowsselected[i]; i+1 != numrows && j < rowsselected[i+1];++j)
                {
                    builder.append(rowDelim);
                }
            }

            StringSelection stsel = new StringSelection(builder.toString());
            system = Toolkit.getDefaultToolkit().getSystemClipboard();
            system.setContents(stsel, stsel);
        }
        else if (e.getActionCommand().compareTo("Paste") == 0)
        {
            if (table.getSelectedColumnCount() != 0
                    && table.getSelectedRowCount() != 0)
            {
                int startRow = (table.getSelectedRows())[0];
                int startColumn = (table.getSelectedColumns())[0];

                try
                {
                    String string = (String) (system.getContents(this).getTransferData(DataFlavor.stringFlavor));

                    String row, value;
                    StringTokenizer rowTokenizer = new StringTokenizer(string, rowDelim, true);

                    int rowCount = table.getRowCount();
                    int columnCount = table.getColumnCount();

                    for (int i = startRow; rowTokenizer.hasMoreTokens()
                            && i < rowCount;)
                    {
                        row = rowTokenizer.nextToken();

                        if (!row.equals(rowDelim))
                        {
                            StringTokenizer columnTokenizer = new StringTokenizer(row, columnDelim, true);

                            for (int j = startColumn; columnTokenizer.hasMoreTokens()
                                    && j < columnCount;)
                            {
                                value = columnTokenizer.nextToken();

                                if (!value.equals(columnDelim))
                                {
                                    table.setValueAt(value, i, j);
                                } else
                                {
                                    ++j;
                                }
                            }
                        } else
                        {
                            ++i;
                        }

                    }
                } catch (UnsupportedFlavorException | IOException ex)
                {
                    System.out.println("Error");
                }
            }
        }
    }
}